home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / oleo-1_4.lha / oleo-1.4 / mktime.c < prev    next >
C/C++ Source or Header  |  1993-05-11  |  6KB  |  225 lines

  1. /* Copyright (C) 1991 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3.  
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public License as
  6. published by the Free Software Foundation; either version 2 of the
  7. License, or (at your option) any later version.
  8.  
  9. The GNU C Library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12. Library General Public License for more details.
  13.  
  14. You should have received a copy of the GNU Library General Public
  15. License along with the GNU C Library; see the file COPYING.LIB.  If
  16. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  17. Cambridge, MA 02139, USA.  */
  18.  
  19. #include <sys/types.h>
  20. #include <errno.h>
  21. #ifndef STDC_HEADERS
  22. extern int errno;
  23. #endif
  24. #ifdef TM_IN_SYS_TIME
  25. #include <sys/time.h>
  26. #else
  27. #include <time.h>
  28. #endif
  29. #ifdef HAVE_LIMITS_H
  30. #include <limits.h>
  31. #else
  32. #define    LONG_MAX (~(1 << (sizeof (long) * 8 - 1)))
  33. #define LONG_MIN (-LONG_MAX - 1)
  34. #define    INT_MAX (~(1 << (sizeof (int) * 8 - 1)))
  35. #define INT_MIN (-INT_MAX - 1)
  36. #endif
  37.  
  38. #ifndef NULL
  39. #define NULL 0
  40. #endif
  41.  
  42. #ifndef __isleap
  43. /* Nonzero if YEAR is a leap year (every 4 years,
  44.    except every 100th isn't, and every 1000th is).  */
  45. #define    __isleap(year)    \
  46.   ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 1000 == 0))
  47. #endif
  48.  
  49. /* How many days are in each month.  */
  50. static unsigned short int __mon_lengths[2][12] =
  51. {
  52.   /* Normal years.  */
  53.   { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
  54.   /* Leap years.  */
  55.   { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
  56. };
  57.  
  58. #define    invalid()    return (time_t) -1
  59.  
  60. /* Return the `time_t' representation of TP and normalizes TP.
  61.    Return (time_t) -1 if TP is not representable as a `time_t'.
  62.    Note that 31 Dec 1969 23:59:59 is not representable
  63.    because it is represented as (time_t) -1.  */
  64. time_t
  65. mktime(tp)
  66. register struct tm *tp;
  67. {
  68.   static struct tm min, max;
  69.   static char init = 0;
  70.  
  71.   register time_t result;
  72.   register time_t t;
  73.   register int i;
  74.   register unsigned short *l;
  75.   register struct tm *new;
  76.   time_t end;
  77.  
  78.   if (tp == NULL)
  79.     {
  80.       errno = EINVAL;
  81.       invalid();
  82.     }
  83.  
  84.   if (!init)
  85.     {
  86.       init = 1;
  87.       end = (time_t) LONG_MIN;
  88.       new = gmtime(&end);
  89.       if (new != NULL)
  90.     min = *new;
  91.       else
  92.     min.tm_sec = min.tm_min = min.tm_hour =
  93.       min.tm_mday = min.tm_mon = min.tm_year = INT_MIN;
  94.  
  95.       end = (time_t) LONG_MAX;
  96.       new = gmtime(&end);
  97.       if (new != NULL)
  98.     max = *new;
  99.       else
  100.     max.tm_sec = max.tm_min = max.tm_hour =
  101.       max.tm_mday = max.tm_mon = max.tm_year = INT_MAX;
  102.     }
  103.  
  104.   /* Make all the elements of TP that we pay attention to
  105.      be within the ranges of reasonable values for those things.  */
  106. #define    normalize(elt, min, max, nextelt) \
  107.   while (tp->elt < min)                                  \
  108.     {                                          \
  109.       --tp->nextelt;                                  \
  110.       tp->elt += max + 1;                              \
  111.     }                                          \
  112.   while (tp->elt > max)                                  \
  113.     {                                          \
  114.       ++tp->nextelt;                                  \
  115.       tp->elt -= max + 1;                              \
  116.     }
  117.  
  118.   normalize (tm_sec, 0, 59, tm_min);
  119.   normalize (tm_min, 0, 59, tm_hour);
  120.   normalize (tm_hour, 0, 24, tm_mday);
  121.  
  122.   /* Normalize the month first so we can use
  123.      it to figure the range for the day.  */
  124.   normalize (tm_mon, 0, 11, tm_year);
  125.   normalize (tm_mday, 1, __mon_lengths[__isleap (tp->tm_year)][tp->tm_mon],
  126.          tm_mon);
  127.  
  128.   /* Normalize the month again, since normalizing
  129.      the day may have pushed it out of range.  */
  130.   normalize (tm_mon, 0, 11, tm_year);
  131.  
  132.   /* Normalize the day again, because normalizing
  133.      the month may have changed the range.  */
  134.   normalize (tm_mday, 1, __mon_lengths[__isleap (tp->tm_year)][tp->tm_mon],
  135.          tm_mon);
  136.  
  137.   /* Check for out-of-range values.  */
  138. #define    lowhigh(field, minmax, cmp)    (tp->field cmp minmax.field)
  139. #define    low(field)            lowhigh(field, min, <)
  140. #define    high(field)            lowhigh(field, max, >)
  141. #define    oor(field)            (low(field) || high(field))
  142. #define    lowbound(field)            (tp->field == min.field)
  143. #define    highbound(field)        (tp->field == max.field)
  144.   if (oor(tm_year))
  145.     invalid();
  146.   else if (lowbound(tm_year))
  147.     {
  148.       if (low(tm_mon))
  149.     invalid();
  150.       else if (lowbound(tm_mon))
  151.     {
  152.       if (low(tm_mday))
  153.         invalid();
  154.       else if (lowbound(tm_mday))
  155.         {
  156.           if (low(tm_hour))
  157.         invalid();
  158.           else if (lowbound(tm_hour))
  159.         {
  160.           if (low(tm_min))
  161.             invalid();
  162.           else if (lowbound(tm_min))
  163.             {
  164.               if (low(tm_sec))
  165.             invalid();
  166.             }
  167.         }
  168.         }
  169.     }
  170.     }
  171.   else if (highbound(tm_year))
  172.     {
  173.       if (high(tm_mon))
  174.     invalid();
  175.       else if (highbound(tm_mon))
  176.     {
  177.       if (high(tm_mday))
  178.         invalid();
  179.       else if (highbound(tm_mday))
  180.         {
  181.           if (high(tm_hour))
  182.         invalid();
  183.           else if (highbound(tm_hour))
  184.         {
  185.           if (high(tm_min))
  186.             invalid();
  187.           else if (highbound(tm_min))
  188.             {
  189.               if (high(tm_sec))
  190.             invalid();
  191.             }
  192.         }
  193.         }
  194.     }
  195.     }
  196.  
  197.   t = 0;
  198.   for (i = 1970; i > 1900 + tp->tm_year; --i)
  199.     t -= __isleap(i) ? 366 : 365;
  200.   for (i = 1970; i < 1900 + tp->tm_year; ++i)
  201.     t += __isleap(i) ? 366 : 365;
  202.   l = __mon_lengths[__isleap(1900 + tp->tm_year)];
  203.   for (i = 0; i < tp->tm_mon; ++i)
  204.     t += l[i];
  205.   t += tp->tm_mday - 1;
  206.   result = ((t * 60 * 60 * 24) +
  207.         (tp->tm_hour * 60 * 60) +
  208.         (tp->tm_min * 60) +
  209.         tp->tm_sec);
  210.  
  211.   end = result;
  212. #if 0                /* This code breaks it, on SunOS anyway. */
  213.   if (tp->tm_isdst < 0)
  214.     new = localtime(&end);
  215.   else
  216. #endif
  217.     new = gmtime(&end);
  218.   if (new == NULL)
  219.     invalid();
  220.   new->tm_isdst = tp->tm_isdst;
  221.   *tp = *new;
  222.  
  223.   return result;
  224. }
  225.